package com.exmaple.dynamicapp.injection;

import android.app.Activity;
import android.util.Log;
import android.view.View;

import com.exmaple.dynamicapp.annotation.EventType;

import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * <p>
 * 注入工具
 * </p>
 *
 * @author 孟祥超
 * <p>
 * date: 2021/8/11
 */
public class InjectionUtils {

    private static final String TAG = "InjectionUtils";

    /**
     * 绑定事件
     * 1.反射获取到在 Activity 声明的方法，找到使用了注解的方法
     * 2.找到使用 EventType 的注解，找到这个注解获取到 事件类，方法，和绑定的 id
     * 3.通过事件类创建动态代理，
     * 5.使用 findViewById 找到对应的 id 设置监听，监听为刚才的动态代理
     *
     * @param activity
     */
    public static void bindViewEvent(Activity activity) {
        Class<? extends Activity> activityClass = activity.getClass();
        Method[] declaredMethods = activityClass.getDeclaredMethods();
        if (null == declaredMethods || declaredMethods.length == 0) return;
        for (Method method : declaredMethods) {
            Annotation[] annotations = method.getAnnotations();
            if (null == annotations || annotations.length == 0) continue;
            for (Annotation annotation : annotations) {
                Class<? extends Annotation> annotationType = annotation.annotationType();//注解类型 ，注解的注解
                if (!annotationType.isAnnotationPresent(EventType.class)) {
                    continue;
                }
                //需要找到那个标注了 @EventType 的注解
                EventType eventType = annotationType.getAnnotation(EventType.class);

                String eventMethod = eventType.eventMethod();
                Class eventTypeClass = eventType.eventType();
                //创建代理
                Object proxyInstance = Proxy.newProxyInstance(activity.getClassLoader(), new Class[]{eventTypeClass},
                        new EventInvocationHandler(activity, method));
                try {
                    Method value = annotationType.getDeclaredMethod("value");
                    int[] ids = (int[]) value.invoke(annotation);
                    for (int id : ids) {
                        View view = activity.findViewById(id);
                        Method setEvent = view.getClass().getMethod(eventMethod, eventTypeClass);
                        setEvent.invoke(view, proxyInstance);
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }


            }
        }
    }
}
